package net.qhzw.vip.qiyu.service.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import net.qhzw.vip.qiyu.entity.*;
import net.qhzw.vip.qiyu.handler.ApiException;
import net.qhzw.vip.qiyu.handler.MyException;
import net.qhzw.vip.qiyu.mapper.SysUserTopupOrderMapper;
import net.qhzw.vip.qiyu.model.LedgerData;
import net.qhzw.vip.qiyu.model.SysUserTopupOrderExcel;
import net.qhzw.vip.qiyu.model.SysUserTopupOrderVo;
import net.qhzw.vip.qiyu.result.PageResult;
import net.qhzw.vip.qiyu.service.*;
import net.qhzw.vip.qiyu.util.MyDateUtils;
import net.qhzw.vip.qiyu.util.PageAdapter;
import net.qhzw.vip.qiyu.util.SecurityUtils;
import org.apache.ibatis.annotations.Param;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
@Slf4j
public class SysUserTopupOrderServiceImpl extends ServiceImpl<SysUserTopupOrderMapper, SysUserTopupOrder>
        implements SysUserTopupOrderService {

    @Autowired
    private SysUserTopupOrderMapper sysUserTopupOrderMapper;

    @Autowired
    private DtsUserService dtsUserService;

    @Autowired
    private DtsUserBillService dtsUserBillService;

    @Autowired
    private UserBillService userBillService;

    @Autowired
    private PayService payService;

    @Autowired
    private DtsCarRentalService dtsCarRentalService;

    @Autowired
    private SysUserService sysUserService;

    /***
     * 用户充值金额
     * @param amount
     * @return
     */
    @Override
    public WxPayMpOrderResult usrRchgGold(BigDecimal amount, Long userId) {
        Long shopId = checked(amount, userId);
        String payNo = IdWorker.getId() + "";
        String notifyUrl = "/lease/sys/user/topupOrder/pay/notify";
        DtsUser dtsUser = dtsUserService.getById(userId);
        if (dtsUser == null || StringUtils.isEmpty(dtsUser.getWeixinOpenid())) {
            throw new ApiException("您的身份信息已过期, 请联系管理员");
        }
        WxPayMpOrderResult orderRequest = payService.usrRchgGold(shopId, dtsUser.getWeixinOpenid(), amount.doubleValue(), payNo, notifyUrl);
        SysUserTopupOrder sysUserTopupOrder = new SysUserTopupOrder();
        long topupOrderId = IdWorker.getId();
        sysUserTopupOrder.setId(topupOrderId);
        sysUserTopupOrder.setAmount(amount);
        sysUserTopupOrder.setUserId(userId);
        sysUserTopupOrder.setType((byte) 1);
        sysUserTopupOrder.setStatus((byte) 0);
        sysUserTopupOrder.setCreated(new Date());
        sysUserTopupOrder.setPayNo(payNo);
        sysUserTopupOrder.setPayTime(new Date());
        sysUserTopupOrder.setIsPayed((byte) 0);
        sysUserTopupOrder.setShopId(shopId);
        save(sysUserTopupOrder);
        return orderRequest;
    }

    /**
     * 用户充值校验
     *
     * @param amount
     * @param userId
     */
    private Long checked(BigDecimal amount, Long userId) {
        if (amount.doubleValue() < 0) {
            throw new ApiException("金额输不合法!");
        }
        if (!isNumber(amount.toString())) {
            throw new ApiException("金额输不合法!");
        }
        LambdaQueryWrapper<DtsCarRental> query = new LambdaQueryWrapper<DtsCarRental>()
                .eq(DtsCarRental::getStatus, 3)
                .eq(DtsCarRental::getUserId, userId);
        int count = dtsCarRentalService.count(query);
        if (count < 0) {
            throw new ApiException("您暂无租车订单!");
        }
        DtsCarRental carRental = dtsCarRentalService.getOne(query);
        if (amount.doubleValue() > carRental.getTotalRent().doubleValue()) {
            throw new ApiException("充值金额不能大于租车时金额,请多次充值!");
        }
        return carRental.getShopId();
    }

    public static boolean isNumber(String str) {
        Pattern pattern = Pattern.compile("^(([1-9]{1}\\d*)|([0]{1}))(\\.(\\d){0,2})?$"); // 判断小数点后2位的数字的正则表达式
        Matcher match = pattern.matcher(str);
        return match.matches();
    }


    /***
     * 分页查询用户充值订单
     * @param page
     * @param userTopupOrderVo
     * @return
     */
    @Override
    public PageResult<SysUserTopupOrderVo> findByPage(Page<SysUserTopupOrder> page, SysUserTopupOrderVo userTopupOrderVo, Long shopId) {
        List<SysUserTopupOrderVo> userTopupOrderVos = sysUserTopupOrderMapper.findByPage(new PageAdapter(page), userTopupOrderVo, shopId);
        Long total = sysUserTopupOrderMapper.pageTotal(userTopupOrderVo, shopId);
        return new PageResult<SysUserTopupOrderVo>(total, userTopupOrderVos);
    }


    /***
     * 后台审核充值
     * @param id
     * @param status
     * @return
     */
    @Override
    @Transactional
    public boolean audit(Long id, Byte status, String auditOpinion, Long userId) {
        Byte statusDB = getStatus(id, status, userId);
        SysUserTopupOrder userTopupOrder = new SysUserTopupOrder();
        userTopupOrder.setStatus(statusDB);
        userTopupOrder.setAuditOpinion(auditOpinion);
        userTopupOrder.setId(id);
        return updateById(userTopupOrder);
    }

    /**
     * 用户充值支付回调
     *
     * @param payNo
     * @param transactionId
     */
    @Override
    public void payNotify(String payNo, String transactionId) {
        LambdaQueryWrapper<SysUserTopupOrder> queryWrapper = new LambdaQueryWrapper<SysUserTopupOrder>()
                .eq(SysUserTopupOrder::getPayNo, payNo);
        SysUserTopupOrder userTopupOrder = getOne(queryWrapper);
        if (userTopupOrder != null) {
            if (userTopupOrder.getIsPayed() == 1) {
                return;
            }
            userTopupOrder.setTransactionId(transactionId);
            userTopupOrder.setIsPayed((byte) 1);
            userTopupOrder.setStatus((byte) 2);
            userTopupOrder.setReviewTime(new Date());
            updateById(userTopupOrder);
            //更新用户余额
            updateUserBalance(userTopupOrder.getUserId(), userTopupOrder.getAmount());
            //新增账单表
            savcUserBill(userTopupOrder.getUserId(), userTopupOrder.getAmount());
        }

    }

    @Override
    public void deleteByUserId(Long userId) {
        sysUserTopupOrderMapper.deleteByUserId(userId);
    }

    /**
     * 新增账单表
     *
     * @param userId
     * @param amount
     */
    private void savcUserBill(Long userId, BigDecimal amount) {
        //新增账单表
        DtsUserBill dtsUserBill = new DtsUserBill();
        long billId = IdWorker.getId();
        dtsUserBill.setId(billId);
        dtsUserBill.setType((byte) 1);
        dtsUserBill.setAmount(amount);
        dtsUserBill.setCreated(new Date());
        dtsUserBill.setUserId(userId);
        dtsUserBillService.save(dtsUserBill);
    }

    /**
     * 更新用户余额
     *
     * @param userId
     * @param amount
     */
    private void updateUserBalance(Long userId, BigDecimal amount) {
        DtsUser dtsUser = dtsUserService.getById(userId);
        if (dtsUser != null) {
            BigDecimal balance = dtsUser.getBalance();
            balance = balance.add(amount);
            dtsUser.setBalance(balance);
            dtsUserService.updateById(dtsUser);
        }
    }


    /***
     * 审核
     * @param id
     * @param status 0:不通过 1:通过
     *       0:待审核 1:审核拒绝 2:审核通过
     * @return
     */
    private Byte getStatus(Long id, Byte status, Long userId) {
        if (status.intValue() == 0) {
            return (byte) 1;
        }
        //更新用户余额
        SysUserTopupOrder userTopupOrder = getById(id);
        DtsUser dtsUser = dtsUserService.getById(userId);
        if (dtsUser == null) {
            throw new MyException("审核失败,参数错误");
        }
        BigDecimal balance = dtsUser.getBalance();
        balance = balance.add(userTopupOrder.getAmount());
        dtsUser.setBalance(balance);
        dtsUserService.updateById(dtsUser);
        //新增账单表
        DtsUserBill dtsUserBill = new DtsUserBill();
        long billId = IdWorker.getId();
        dtsUserBill.setId(billId);
        dtsUserBill.setType((byte) 1);
        dtsUserBill.setAmount(userTopupOrder.getAmount());
        dtsUserBill.setCreated(new Date());
        dtsUserBill.setUserId(userId);
        dtsUserBillService.save(dtsUserBill);
        return (byte) 2;
    }

    /***
     * 导出充值订单
     * @param response
     * @param userTopupOrderVo
     * @return
     */
    @Override
    public void exportLedger(HttpServletResponse response, Long shopId,SysUserTopupOrderVo userTopupOrderVo){
        Long userId = SecurityUtils.getUserId();
        SysUser user = sysUserService.getById(userId);
        if (user == null || user.getCommunityId() == null) {
            return;
        }

        List<SysUserTopupOrderExcel> ledgerDataList = sysUserTopupOrderMapper.findLedger(shopId, userTopupOrderVo);
        if (CollectionUtils.isEmpty(ledgerDataList)) {
            return;
        }

        for (int i = 0; i < ledgerDataList.size(); i++) {
            SysUserTopupOrderExcel ledgerData = ledgerDataList.get(i);
            ledgerData.setId(Long.valueOf(1 + i));
        }

        log.info("【" + MyDateUtils.getCurDt() + "导出台账：】{}", JSON.toJSONString(ledgerDataList));
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams( "充值订单", MyDateUtils.getCurDt()), SysUserTopupOrderExcel.class, ledgerDataList);
        try {
            response.setHeader("content-disposition", "attachment;fileName=" + URLEncoder.encode( "充值订单.xls", "UTF-8"));
            ServletOutputStream os = response.getOutputStream();
            workbook.write(os);
            os.close();
            workbook.close();
        } catch (IOException e) {
            log.error("【导出台账,错误】{}", JSON.toJSONString(e, true));
        }
    }


}
